#!/bin/bash

usage="\
Usage:
	oc-ops cpu irq latency [-e val] [-f freq_ms] [-t threshold_ms] [-c] [-k] [-h]
        COMMAND-LINE Options:
	-e	使能/去使能irq latency的检测，-e参数后面只能传两种值之一： 1 或者 0，1表示开启监控，0表示关闭监控
	-f	设置监控时采样的频率所对应的时间，单位为ms，取值范围为[4ms, 1000ms] (默认值为10ms)
	-t	设置latency的阈值，单位为ms，取值范围为[freq_ms, 30000ms] (默认值为30ms)；中断响应latency超过阈值时相关的栈信息将打印出来;
		上限设置的原因：如果关中断的时延超过30000ms，soft lockup特性能检测出来
	-c	clear已积累的栈信息
	-k	为避免忘记关闭检测而对系统造成污染，oc-ops cpu irq latency将默认在3600s后关闭检测；-k表示 keep irq latency的检测，永远不会自动关闭
	-h	显示 oc-ops cpu irq latency 的用法

其他信息:
	使能后，每60s自动打印检测的结果；如想主动看检测结果，可执行下面两条命令主动获取:
	cat /proc/irq_latency/trace_dist
	cat /proc/irq_latency/trace_stack
"
if (( $# < 1 )); then
	echo "$usage"
	exit 1
fi

lsmod | grep irqlatency > /dev/null
if (( $? != 0 )); then
	modprobe irqlatency 1>/dev/null 2>&1
	if (( $? != 0 )); then
		echo "Error: modprobe irqlatency fail! We add the feature recently, so, please use a newer kernel verison."
		arch_val=$( uname -a | grep "x86" | wc -l )
		if (( $arch_val == 0 )); then
			echo "Note: We only support irqlatency on x86/x86_64 architecture."
		fi
		exit 1
	fi
fi

workdir=$(readlink /proc/$$/fd/255); workdir=$(dirname $workdir); cd "$workdir"

irq_latency_enable=0
freq_ms=10
threshold_ms=30
keep_monitor=0

clear_stack_info()
{
	echo "0" > /proc/irq_latency/trace_stack
}

disable_irq_latency()
{
	echo "0" > /proc/irq_latency/enable
	clear_stack_info
	killall irq_latency_show.sh 2>/dev/null
	exit 0
}

enable_val_set()
{
	if (( $irq_latency_enable != 0 && $irq_latency_enable != 1 )); then
		echo "Error: -e val is $irq_latency_enable, which must be 0 or 1 !" ; exit 1
	fi

	if (( $irq_latency_enable == 0 )); then
		disable_irq_latency
	else
		echo "1" > /proc/irq_latency/enable
		./irq_latency_show.sh &
	fi
}

freq_ms_set()
{
	if (( $freq_ms < 4 || $freq_ms > 1000 )); then
		echo "Error: -f freq_ms is $freq_ms, which should be in [4ms, 1000ms] !" ; exit 1
	fi

	echo "$freq_ms" >  /proc/irq_latency/freq_ms
}

threshold_ms_set()
{
	if (( $threshold_ms < $freq_ms || $threshold_ms > 30000 )); then
		echo "Error: -t threshold_ms is $threshold_ms, which should be in [freq_ms, 1000ms] !" ; exit 1
	fi

	echo "$threshold_ms" >  /proc/irq_latency/latency_thresh_ms
}

while getopts 'e:f:t:ckh' OPT; do
        case $OPT in
                e) 	irq_latency_enable="$OPTARG"
			enable_val_set
                        ;;
		f)	freq_ms_set="$OPTARG"
			freq_ms_set
			;;
		t)	threshold_ms_set="$OPTARG"
			threshold_ms_set
			;;
		c)	clear_stack_info
			;;
		k)	keep_monitor=1
			;;
                h)	echo "$usage"
                        exit $?
			;;
                ?)	echo "Invalid option: $OPT" >&2
                        echo "$usage"
                        exit 1
			;;
        esac
done

if (( $irq_latency_enable == 1 && $keep_monitor == 0 )); then
	$( sleep 3600; disable_irq_latency ) &
fi
